/**
 *  sem.h - Semaphore Mechanism.
 *
 *  Copyright (C) 2008-2009 ZhangHu
 *  All rights reserved.
 *  E-MAIL: anmnmnly@gmail.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


#ifndef __SEM_H__
#define __SEM_H__

#include "include/types.h"

#ifndef UNIT_DEBUG
#include "include/list.h"
#include "include/core.h"
#include "include/mem.h"
#include "include/irq.h"
#endif


#ifndef semid_t
#define semid_t  uword_t
#endif


typedef struct semaphore {
    uword_t sem_id;     /* Semaphore ID */
    word_t sem_cnt;     /* value */
    uword_t task_cnt;   /* Count all blocked tasks */
    slist_t tcb_link;   /* TCB links the locked semaphore with this member */
    list_t sem_link;    /* All semaphores linked by this member */
    list_t task_link[MAX_PRIO]; /* Waiting queue */
} sem_t;

/* Initialize semaphore */
void initsem(void);

/* Unlock all semaphores that a task locked */
void release_sem(tcb_t *ptcb);


/* APIs */

/* Creating a semaphore */
sem_t *semInit(semid_t SemID,       /* The ID of new semaphore */
               uword_t InitCnt);    /* The initial count value of new semaphore */

/* Creating a mutex semaphore */
sem_t *semInitMutex(semid_t SemID);  /* The ID of new semaphore */


/* Get semaphore */
void semGain(semid_t SemID,         /* The ID of new semaphore */
             sem_t *pSemaphore);    /* Pointer to semaphore */


/* Get semaphore without block */
bool_t semGainFree(semid_t SemID,     /* The ID of new semaphore */
                   sem_t *pSemaphore);/* Pointer to semaphore */


/* Unlock a semaphore */
void semPost(semid_t SemID,      /* The ID of new semaphore */
             sem_t *pSemaphore); /* Pointer to semaphore */

/* Deleting a semaphore */
void semDel(semid_t SemID,          /* The ID of new semaphore */
            sem_t *pSemaphore);     /* Pointer to semaphore */

#endif

